#pragma once

#include "Thread.hpp"
#include <vector>
#include <queue>
#define NUM 5
namespace yui
{
    template<class T>
    class ThreadPool
    {
        using func_t = std::function<void(T&)>;
        private:
            void LockQueue()
            {
                pthread_mutex_lock(&_mutex);
            }
            void UnlockQueue()
            {
                pthread_mutex_unlock(&_mutex);
            }
            void ThreadWakeup()
            {
                pthread_cond_signal(&_cond);
            }
            void ThreadSleep()
            {
                pthread_cond_wait(&_cond,&_mutex);
            }
            bool IsTaskEmpty()
            {
                return _tasks.empty();
            }
        public:
            ThreadPool(int num = NUM)
                :_threadNum(num)
            {
                //初始化，互斥锁与条件变量
                pthread_mutex_init(&_mutex,nullptr);
                pthread_cond_init(&_cond,nullptr);
            }
            ~ThreadPool()
            {
                //销毁条件变量、互斥锁
                pthread_mutex_destroy(&_mutex);
                pthread_cond_destroy(&_cond);
            }
            void init()
            {
                for(int i = 0;i<_threadNum;++i)
                {
                    std::string name = "thread-"+std::to_string(i+1);
                    _threads.emplace_back(std::bind(&ThreadPool::HanderTask,this,std::placeholders::_1),name);
                }
            }
            void start()
            {
                for(auto&x:_threads)
                {
                    x.Start();
                }
            }
            void HanderTask(std::string name)
            {
                //pthread_detach(pthread_self());
                while(true)
                {
                    LockQueue();//启动锁
                    while(IsTaskEmpty())
                    {
                        ThreadSleep();
                    }
                    T task = _tasks.front();
                    _tasks.pop();
                    std::cout<<"获得任务："<<task<<std::endl;
                    UnlockQueue();//解锁
                }
            }
            void pushTask(const T& task)
            {
                LockQueue();
                _tasks.push(task);
                ThreadWakeup();
                UnlockQueue();
            }
        private:
            std::vector<yui::Thread> _threads;
            int _threadNum;
            std::queue<T> _tasks;
            pthread_mutex_t _mutex;
            pthread_cond_t _cond;
    };
}